package administrator;

import gui.MainFrame;
import gui.houseeditor.HouseModel;
import gui.houseeditor.Stanza;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.util.LinkedList;
import java.util.List;
import java.util.StringTokenizer;

import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

import sde.actor.ControlMachine;
import sde.actor.Realtime;
import util.Casella;
import android.rmi.GestoreSensori;
import android.rmi.GestoreSensoriImpl;
import attori.attuatori.AttuatoreLuce;
import attori.attuatori.AttuatoreLuceIF;
import attori.attuatori.AttuatorePorta;
import attori.attuatori.AttuatorePortaIF;
import attori.attuatori.AttuatoreTemperatura;
import attori.attuatori.AttuatoreTemperaturaIF;
import attori.controller.ControllerLuce;
import attori.controller.ControllerLuceIF;
import attori.controller.ControllerPorta;
import attori.controller.ControllerPortaIF;
import attori.controller.ControllerTemperatura;
import attori.controller.ControllerTemperaturaIF;
import attori.proattivi.ModificatoreTemperatura;
import attori.sensori.Sensore;
import attori.sensori.SensorePorta;
import attori.sensori.SensoreTemperatura;
import attori.sensori.SensoreVolume;

public class Administrator {
	/*
	 * classe controller per il pattern Model-View-Controller
	 */
	public MainFrame gui;
	public HouseModel model;
	public List<ControllerTemperaturaIF> controllerTemperatura;
	public ControlMachine cm;

	public Administrator(File mapLocation, File roomDistribution) {
		 cm = new Realtime();
		try {

			UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
		} catch (UnsupportedLookAndFeelException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		}

		// creo la GUI principale
		gui = new MainFrame(mapLocation);
		gui.setVisible(true);
		// il model viene inizializzato nella gui e poi prelevato per essere
		// assegnato a tutti gli oggetti che necessitano di conoscerlo
		model = gui.getHouseModel();
		// creo la parte del model CasaModel
		initCasaModel(roomDistribution);
		initAttoriPorta();
		initAttoriLuce();
		controllerTemperatura = initAttoriTemperatura();
		initAttoriProattivi();
		gui.setControllerTemperatura(controllerTemperatura);
		/*
		 * TODO creare un sensore ed un attuatore per ogni stanza e passargli le
		 * stanze corrispondenti. Creare un sensore per ogni porta e fargli
		 * conoscere il modello relativo. Istanziare i controller per completare
		 * l'architettura
		 */
		// in ultimo lanciare la control machine
		
//		TOLTO MOMENTANEAMENTE
//		cm.controller();
	}

	private void initAttoriProattivi() {
		List<Stanza> stanze = model.getStanze();
		new ModificatoreTemperatura(stanze, 5000);
	}

	private List<ControllerTemperaturaIF> initAttoriTemperatura() {
		List<Stanza> stanze = model.getStanze();
		List<ControllerTemperaturaIF> controllerList = new LinkedList<ControllerTemperaturaIF>();
		for (Stanza stanza : stanze) {
			AttuatoreTemperaturaIF attuatore = new AttuatoreTemperatura();
			attuatore.send(new AttuatoreTemperaturaIF.Init(stanza));
			ControllerTemperaturaIF controller = new ControllerTemperatura();
			controllerList.add(controller);
			controller
					.send(new ControllerTemperaturaIF.Init(30, 20, attuatore));
			Sensore sensore = new SensoreTemperatura(stanza, controller, 1000);
			stanza.setSensoreTemperatura(sensore);
		}
		return controllerList;
	}

	private void initAttoriLuce() {
		List<Stanza> stanze = model.getStanze();
		for (Stanza stanza : stanze) {
			AttuatoreLuceIF attuatore = new AttuatoreLuce();
			attuatore.send(new AttuatoreLuceIF.Init(stanza));
			ControllerLuceIF controller = new ControllerLuce();
			controller.send(new ControllerLuceIF.Init(attuatore, stanza
					.getVolumeIniziale()));
			Sensore sensore = new SensoreVolume(stanza, controller, 10);
			stanza.setSensoreVolume(sensore);
		}
	}

	private void initAttoriPorta() {
		List<Casella[]> porta = model.getPorte();
		List<Casella[][]> area = model.getAreaPorte();
		for (int i = 0; i < porta.size(); i++) {
			AttuatorePortaIF attuatore = new AttuatorePorta();
			attuatore.send(new AttuatorePortaIF.Init(model, porta.get(i)));
			ControllerPortaIF controller = new ControllerPorta();
			controller.send(new ControllerPortaIF.Init(attuatore, 600));
			Sensore s = new SensorePorta(model, area.get(i), controller, 50);
			model.addSensore(s);
		}
	}

	private void initCasaModel(File roomDistribution) {
		BufferedReader br = null;
		try {
			br = new BufferedReader(new FileReader(roomDistribution));
			List<Stanza> stanze = new LinkedList<Stanza>();
			String stanza = br.readLine();
			while (stanza != null) {
				stanze.add(createStanza(stanza));
				stanza = br.readLine();
			}
			model.setStanze(stanze);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				br.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	private Stanza createStanza(String stanza) {
		StringTokenizer st = new StringTokenizer(stanza, ":,;", false);
		String nome = st.nextToken();
		String righe = st.nextToken();
		String colonne = st.nextToken();
		int rigaInizio = getToken(righe, 0);
		int rigaFine = getToken(righe, 1);
		int colonnaInizio = getToken(colonne, 0);
		int colonnaFine = getToken(colonne, 1);
		int temperatura = Integer.parseInt(st.nextToken());
		return new Stanza(nome, temperatura, model, rigaInizio, rigaFine,
				colonnaInizio, colonnaFine);

	}

	private int getToken(String righe, int i) {
		StringTokenizer st = new StringTokenizer(righe, "-", false);
		String token = st.nextToken();
		for (int j = 0; j < i; j++) {
			token = st.nextToken();
		}
		return Integer.parseInt(token);
	}

	public static void main(String[] args) {
		Administrator adm = new Administrator(new File("mappe/casaProva"),
				new File("stanze/casaProva"));

		try {
			try {
				GestoreSensori gestoreSensori = new GestoreSensoriImpl(
						adm.model, adm.controllerTemperatura);
				
				LocateRegistry.createRegistry(1099);
				Naming.rebind("GestoreSensori", gestoreSensori);
				System.out.println("OK");
				adm.cm.controller();
				
			} catch (MalformedURLException e) {
				e.printStackTrace();
			}

		} catch (RemoteException e) {
			e.printStackTrace();
		}

	}
}
